﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Practices.ObjectBuilder;
using WPFCABShell.Shell.Interface.Services.Command;
using Shortcuts.Services;
using WPF = System.Windows.Input;

namespace Shortcuts
{
	public partial class ShortcutsView : UserControl, IShortcutsView
	{
		public static readonly DependencyProperty PresenterProperty = DependencyProperty.Register("Presenter",
			typeof(ShortcutsPresenter),
			typeof(ShortcutsView),
			new FrameworkPropertyMetadata(Presenter_Changed));

		public static readonly DependencyProperty GroupUnderEditProperty = DependencyProperty.Register("GroupUnderEdit",
			typeof(IShortcutGroup),
			typeof(ShortcutsView));

		[CreateNew]
		public ShortcutsPresenter Presenter
		{
			get
			{
				return GetValue(PresenterProperty) as ShortcutsPresenter;
			}
			set
			{
				SetValue(PresenterProperty, value);
			}
		}

		public new ContextMenu ContextMenu
		{
			get
			{
				return Resources["ContextMenu"] as ContextMenu;
			}
		}

		public IShortcutGroup GroupUnderEdit
		{
			get
			{
				return GetValue(GroupUnderEditProperty) as IShortcutGroup;
			}
			set
			{
				SetValue(GroupUnderEditProperty, value);
			}
		}

		public Window Window
		{
			get
			{
				DependencyObject parent = LogicalTreeHelper.GetParent(this);

				while (parent != null && !(parent is Window))
				{
					parent = LogicalTreeHelper.GetParent(parent);
				}

				return parent as Window;
			}
		}

		public ShortcutsView()
		{
			//can't use binding to set converter because Binding.Converter isn't a dprop
			//can't use nested class from XAML (don't want top-level class in this case)
			//must set this resource before InitializeComponent() is called
			Resources["UnderEditConverter"] = new ShortcutsPresenter.UnderEditConverter();

			InitializeComponent();
		}

		public void InvalidGroupName()
		{
			MessageBox.Show("The group name cannot be empty.", "Invalid Group Name", MessageBoxButton.OK, MessageBoxImage.Error);
		}

		public bool ConfirmDelete(IShortcutGroup group)
		{
			Debug.Assert(group != null);
			return MessageBox.Show(string.Format("Are you sure you want to delete the '{0}' shortcut group?", group.Name), "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes;
		}

		public bool ConfirmDelete(IShortcut shortcut)
		{
			Debug.Assert(shortcut != null);
			return MessageBox.Show(string.Format("Are you sure you want to delete the '{0}' shortcut?", shortcut.Command.Name), "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes;
		}

		private void _groupNameTextBox_PreviewLostKeyboardFocus(object sender, WPF.KeyboardFocusChangedEventArgs e)
		{
			Debug.Assert(sender is TextBox);
			TextBox textBox = sender as TextBox;

			if (!Presenter.FinishGroupRename())
			{
				e.Handled = true;
				textBox.SelectAll();
				textBox.Focus();
			}
		}

		private void _groupNameTextBox_PreviewTextInput(object sender, WPF.TextCompositionEventArgs e)
		{
			Debug.Assert(sender is TextBox);
			TextBox textBox = sender as TextBox;

			if (e.Text == "\r" || e.Text == "\t")
			{
				e.Handled = true;

				if (!Presenter.FinishGroupRename())
				{
					textBox.SelectAll();
					textBox.Focus();
				}
			}
		}

		private void _shortcutGroupCommand_CanExecute(object sender, WPF.CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = e.Parameter is IShortcutGroup || e.Parameter is IShortcut;
		}

		private void _shortcutCommand_CanExecute(object sender, WPF.CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = e.Parameter is IShortcut;
		}

		private void _renameShortcutGroup_Executed(object sender, WPF.ExecutedRoutedEventArgs e)
		{
			Debug.Assert(e.Parameter is IShortcutGroup || e.Parameter is IShortcut);
			IShortcutGroup group = e.Parameter as IShortcutGroup ?? (e.Parameter as IShortcut).Group;
			Debug.Assert(group != null);
			Presenter.RenameGroup(group);
		}

		private void _deleteShortcutGroup_Executed(object sender, WPF.ExecutedRoutedEventArgs e)
		{
			Debug.Assert(e.Parameter is IShortcutGroup || e.Parameter is IShortcut);
			IShortcutGroup group = e.Parameter as IShortcutGroup ?? (e.Parameter as IShortcut).Group;
			Debug.Assert(group != null);
			Presenter.DeleteGroup(group);
		}

		private void _addShortcut_Executed(object sender, WPF.ExecutedRoutedEventArgs e)
		{
			Debug.Assert(e.Parameter is IShortcutGroup || e.Parameter is IShortcut);
			IShortcutGroup group = e.Parameter as IShortcutGroup ?? (e.Parameter as IShortcut).Group;
			Debug.Assert(group != null);
			Presenter.AddShortcut(group);
		}

		private void _deleteShortcut_Executed(object sender, WPF.ExecutedRoutedEventArgs e)
		{
			Debug.Assert(e.Parameter is IShortcut);
			IShortcut shortcut = e.Parameter as IShortcut;
			Debug.Assert(shortcut != null);
			Presenter.DeleteShortcut(shortcut);
		}

		private void _textBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
		{
			Debug.Assert(sender is TextBox);
			Debug.Assert(e.Property == TextBox.IsVisibleProperty);
			TextBox textBox = sender as TextBox;

			if ((bool)e.NewValue)
			{
				textBox.SelectAll();
				textBox.Focus();
			}
		}

		private void _itemsControl_MouseRightButtonUp(object sender, WPF.MouseButtonEventArgs e)
		{
			if ((e.ClickCount == 1) && (e.OriginalSource is FrameworkElement) || (e.OriginalSource is FrameworkContentElement))
			{
				object dataContext = null;

				if (e.OriginalSource is FrameworkElement)
				{
					dataContext = (e.OriginalSource as FrameworkElement).DataContext;
				}
				else
				{
					dataContext = (e.OriginalSource as FrameworkContentElement).DataContext;
				}

				Presenter.SelectShortcutGroupOrShortcut(dataContext);
			}
		}

		private static void Presenter_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
		{
			Debug.Assert(dependencyObject is ShortcutsView);

			if (e.NewValue != null)
			{
				Debug.Assert(e.NewValue is ShortcutsPresenter);
				(e.NewValue as ShortcutsPresenter).View = dependencyObject as ShortcutsView;
			}
		}
	}
}
